package com.tjc.happy8;

import java.io.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {
    public static void main(String[] args) throws IOException, SQLException, ClassNotFoundException {
        clearDB();
        List<Data> list = loadDatas("C:\\Users\\50191\\Documents\\code\\java\\happy8\\happy8.txt");
        insertDB(Collections.unmodifiableList(list));

    }

    private static void clearDB() throws SQLException, ClassNotFoundException {
        Class.forName("com.mysql.cj.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/happy8", "root", "111111");
        Statement stmt = conn.createStatement();
        int res = stmt.executeUpdate("delete from happy8");
    }

    public static List<Data> loadDatas(String path) throws IOException {
        List<Data> dataList = new ArrayList<>(100000);
        long time1 = System.currentTimeMillis();
        Reader reader = new InputStreamReader(new FileInputStream(path));
        BufferedReader reader1 = new BufferedReader(reader);
        String line = null;
        while ((line = reader1.readLine()) != null) {
            String[] parts = line.split(",");
            String issue = parts[0];
            int number1 = units(sum(Arrays.copyOfRange(parts, 1, 7)));
            int number2 = units(sum(Arrays.copyOfRange(parts, 7, 13)));
            int number3 = units(sum(Arrays.copyOfRange(parts, 13, 19)));
//            System.out.println(String.format("%s %s %s %s", issue, number1, number2, number3));
            int winningNumber = number1 + number2 + number3;
            int bigSmall = winningNumber > 13 ? 1 : 0;
            int evenOdd = (winningNumber & 0x1) > 0 ? 1 : 0;
            dataList.add(new Data(Integer.parseInt(issue), winningNumber, bigSmall, evenOdd));
        }
        reader.close();
        long time2 = System.currentTimeMillis();
        System.out.println(String.format("load file cost: %s, count: %s", (time2 - time1), dataList.size()));
        return dataList;
    }

    public static void insertDB(final List<Data> dataList) {
        long time1 = System.currentTimeMillis();
        ConnPoolConfig config = new ConnPoolConfig();
        ConnectionPool pool = null;
        try {
            pool = new ConnectionPool(config);
        } catch (Exception e) {
            throw new RuntimeException("conn pool init fail.");
        }
        ExecutorService threadPool = Executors.newFixedThreadPool(6);
        List<List<Data>> batchdatas = getBatchs(dataList, 10000);

        for (List<Data> datas : batchdatas) {
            ConnectionPool finalPool = pool;
            threadPool.submit(() -> {
                Connection conn = finalPool.getConnection();
                try {
                    Statement stmt = conn.createStatement();

                    StringJoiner joiner = new StringJoiner(",");
                    datas.stream().forEach((d -> {
                        String.format("(%s, %s, %s, %s)", d.id, d.winningNum, d.bigSmall, d.evenOdd);
                    }));
                    int res = stmt.executeUpdate("insert into happy8 (id, winning_number, big_small, even_odd) values " + joiner.toString());
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                finalPool.recycle(conn);

            });
        }

        threadPool.shutdown();
        while (!threadPool.isTerminated()) {
        }
        long time2 = System.currentTimeMillis();
        System.out.println("insert db cost: " + (time2 - time1));
    }

    private static List<List<Data>> getBatchs(List<Data> dataList, int batchSize) {
        List<List<Data>> batchdatas = new ArrayList<>();

        int size = dataList.size();
        for (int start = 0, end = 0; start < size; start = end) {
            end = start + batchSize > size ? size : start + batchSize;
            batchdatas.add(dataList.subList(start, end));
        }
        return batchdatas;
    }

    private static int units(int a) {
        String str = String.valueOf(a);
        return Integer.parseInt(String.valueOf(str.charAt(str.length() - 1)));
    }

    private static int sum(String... arr) {
        int res = 0;
        for (String str : arr) {
            res += Integer.parseInt(str);
        }
        return res;
    }
}

class Data {
    int id;
    int winningNum;
    int bigSmall;
    int evenOdd;

    public Data(int id, int winningNum, int bigSmall, int evenOdd) {
        this.id = id;
        this.winningNum = winningNum;
        this.bigSmall = bigSmall;
        this.evenOdd = evenOdd;
    }
}
